home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 17.7 KB | 511 lines | [TEXT/MPS ] |
- //========================================================================================
- //
- // File: FWArDyna.cpp
- // Release Version: $ ODF 2 $
- //
- // Copyright: (c) 1993 - 1996 by Apple Computer, Inc., all rights reserved.
- //
- //========================================================================================
-
- #include "FWFound.hpp"
-
- #ifndef FWEXCEPT_H
- #include "FWExcept.h"
- #endif
-
- #ifndef FWARDYNA_H
- #include "FWArDyna.h"
- #endif
-
- #ifndef FWPRISTR_H
- #include "FWPriStr.h"
- #endif
-
- #ifndef FWPRIDEB_H
- #include "FWPriDeb.h"
- #endif
-
- #ifndef FWARCOBJ_K
- #include "FWArcObj.k"
- #endif
-
- #ifdef FW_DEBUG
- #include <stdio.h>
- #endif
-
- #include "FWTMap.tpp"
-
- #ifdef FW_BUILD_MAC
- #pragma segment FWArchiv
- #endif
-
- //========================================================================================
- // Constants having file scope
- //========================================================================================
-
- const short kIDOnly = FW_kPrivIDOnly;
- const short kIDAndValue = FW_kPrivIDAndValue;
-
- const FW_ObjectRegistry_ID kNotInRegistry = FW_kPrivNotInRegistry;
- const FW_ObjectRegistry_ID kNULLObjectID = FW_kPrivNULLObjectID;
-
- //========================================================================================
- // Keys Matching Function
- //========================================================================================
-
- static int FW_PrivCompareNames(void* first, void* second);
- static int FW_PrivCompareLabels(void* first, void* second);
-
- //========================================================================================
- // Template Instantiations
- //========================================================================================
-
- #ifdef FW_USE_TEMPLATE_PRAGMAS
-
- #pragma template_access public
- #pragma template FW_TMap<FW_SPrivArcStr, FW_ClassTypeConstant>
- #pragma template FW_TMap<FW_ClassTypeConstant, FW_SPrivArcFun>
-
- #else
-
- template class FW_TMap<FW_SPrivArcStr, FW_ClassTypeConstant>;
- template class FW_TMap<FW_ClassTypeConstant, FW_SPrivArcFun>;
-
- #endif
-
- static void* ClassLabel_Create(FW_CReadableStream& stream, FW_ClassTypeConstant type);
- static void ClassLabel_Output(FW_CWritableStream& stream, FW_ClassTypeConstant type, const void *object);
-
- FW_ClassTypeConstant kMetaClassTypeConstant = FW_TYPE_CONSTANT('c', 'l', 'a', 's');
- FW_CPrivArchiver gFWArchiveMetaClass(kMetaClassTypeConstant, FW_SPrivArcFun(ClassLabel_Create, 0, 0, ClassLabel_Output));
-
- //========================================================================================
- // Class FW_CPrivArchiver
- //========================================================================================
-
- FW_SPrivArchiverGlobals FW_CPrivArchiver::fgGlobals;
-
- //----------------------------------------------------------------------------------------
- // FW_CArchiveDictionary& FW_CPrivArchiver::GetNameToLabelMap
- //----------------------------------------------------------------------------------------
-
- FW_CPrivNameToLabelMap& FW_CPrivArchiver::GetNameToLabelMap()
- {
- return *GetArchiverGlobals().gNameToLabelMap;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CArchiveDictionary& FW_CPrivArchiver::GetLabelToIOFunctionMap
- //----------------------------------------------------------------------------------------
-
- FW_CPrivLabelToIOFunctionMap& FW_CPrivArchiver::GetLabelToIOFunctionMap()
- {
- return *GetArchiverGlobals().gLabelToIOFunctionMap;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::GetArchiverGlobals
- //----------------------------------------------------------------------------------------
-
- FW_SPrivArchiverGlobals& FW_CPrivArchiver::GetArchiverGlobals()
- {
- FW_SPrivArchiverGlobals *globals = &fgGlobals;
-
- if (globals->gNameToLabelMap == 0)
- Initialize(*globals);
- return *globals;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::AddNameToLabelPair
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivArchiver::AddNameToLabelPair(FW_ClassTypeConstant classLabel, const char* className)
- {
- #ifdef FW_DEBUG
- FW_ASSERT(("Can't register a class as archivable if it doesn't have RTTI.", className != 0));
- FW_CPrivNameToLabelPair* pair = GetNameToLabelMap().Find(FW_SPrivArcStr(className));
- if (pair !=0)
- {
- char buffer[256];
- sprintf(buffer, "Class %s has already been registered as archivable!", className);
- FW_DEBUG_MESSAGE(buffer);
- }
- #endif
-
- GetNameToLabelMap()[FW_SPrivArcStr(className)] = classLabel;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::AddLabelToIOFunctionPair
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivArchiver::AddLabelToIOFunctionPair(FW_ClassTypeConstant classLabel, const FW_SPrivArcFun& functions)
- {
- #ifdef FW_DEBUG
- FW_ASSERT(GetLabelToIOFunctionMap().Find(classLabel) == 0);
- #endif
-
- GetLabelToIOFunctionMap()[classLabel] = functions;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::FW_CPrivArchiver
- //----------------------------------------------------------------------------------------
-
- FW_CPrivArchiver::FW_CPrivArchiver(FW_ClassTypeConstant classLabel,
- const char* className,
- const FW_SPrivArcFun& functions)
- {
- AddNameToLabelPair(classLabel, className);
- AddLabelToIOFunctionPair(classLabel, functions);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::FW_CPrivArchiver
- //----------------------------------------------------------------------------------------
-
- FW_CPrivArchiver::FW_CPrivArchiver(FW_ClassTypeConstant classLabel,
- const FW_SPrivArcFun& functions)
- {
- AddLabelToIOFunctionPair(classLabel, functions);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::PreregisterSpecialObject
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivArchiver::PreregisterRuntimeObject(
- FW_OObjectRegistry* registry,
- const void* object,
- FW_ObjectRegistry_ID objectID)
- {
- FW_SOMEnvironment ev;
- registry->RegisterObjectAndID(ev, (void*) object, objectID);
- }
-
- //----------------------------------------------------------------------------------------
- // ClassLabel_Create
- //
- // Notes:
- // 1. You may have expected this method to return a pointer to the class label. Doing
- // so, however, would result in two problems. First, the pointer returned would have
- // to be to a buffer allocated by this method and who would delete it? Second, even
- // if a pointer to a class label was returned, by returning a FW_SPrivArcFun
- // pointer, we only have to map a particular class label once (via the map
- // 'gLabelToIOFunctionMap') for the entire 'readableStream'. That is,
- // if there are "n" occurrences of a particular class label in a 'readableStream',
- // one reference to 'gLabelToIOFunctionMap' is made instead of "n".
- //----------------------------------------------------------------------------------------
-
- static void* ClassLabel_Create(FW_CReadableStream& stream, FW_ClassTypeConstant type)
- {
- FW_UNUSED(type);
- // Read the class label of the object from the archive.
- FW_ClassTypeConstant label;
- stream >> label;
- FW_CPrivLabelToIOFunctionPair* pair = FW_CPrivArchiver::LookupArchivingFunctions(label);
- if (pair == NULL)
- {
- // If you get this assertion there is a good chance that it's because you loaded
- // views from resources and forgot to use the macro FW_DO_NOT_DEAD_STRIP in your
- // code for those classes that are not referenced anywhere else, for instance
- // FW_DO_NOT_DEAD_STRIP(FW_CGrowBox). See the ODF samples.
- #ifdef FW_DEBUG
- char msg[255];
- char* c = (char*)&label;
- sprintf(msg, "'%c%c%c%c' class not registered for archiving. Forgot FW_DO_NOT_DEAD_STRIP ?", c[0],c[1],c[2],c[3]);
- FW_DEBUG_MESSAGE(msg);
- #endif
- }
- return pair;
- }
-
- //----------------------------------------------------------------------------------------
- // ClassLabel_Output
- //----------------------------------------------------------------------------------------
-
- static void ClassLabel_Output(FW_CWritableStream& stream, FW_ClassTypeConstant type, const void *object)
- {
- FW_UNUSED(type);
- FW_CPrivLabelToIOFunctionPair* item = (FW_CPrivLabelToIOFunctionPair*) object;
- FW_ClassTypeConstant label = item->fKey;
- stream << label;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::LookupArchivingFunctions
- //----------------------------------------------------------------------------------------
-
- FW_CPrivLabelToIOFunctionPair* FW_CPrivArchiver::LookupArchivingFunctions(FW_ClassTypeConstant label)
- {
- static FW_CPrivLabelToIOFunctionPair* gCachedMetaPair = GetLabelToIOFunctionMap().Find(kMetaClassTypeConstant);
- FW_CPrivLabelToIOFunctionPair* result = 0;
- if (kMetaClassTypeConstant == label)
- result = gCachedMetaPair;
- else
- result = GetLabelToIOFunctionMap().Find(label);
- return result;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::CreateObject
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivArchiver::CreateObject(FW_CReadableStream& readableStream, void*& object)
- {
- FW_CPrivLabelToIOFunctionPair* pair = (FW_CPrivLabelToIOFunctionPair*)
- PrivCreateObject(readableStream, kMetaClassTypeConstant);
- object = PrivCreateObject(readableStream, pair ? pair->fKey : FW_kNullTypeConstant);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::OutputObject
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivArchiver::OutputObject(FW_CWritableStream& writableStream,
- const void* object,
- const char* className)
- {
- if (!object)
- {
- writableStream << kIDOnly << kNULLObjectID; // Null class
- writableStream << kIDOnly << kNULLObjectID; // Null object
- }
- else
- {
- FW_SPrivArcStr tempName(className);
- FW_ASSERT(GetNameToLabelMap().Find(tempName));
- FW_ClassTypeConstant label = GetNameToLabelMap()[tempName];
-
- FW_CPrivLabelToIOFunctionPair* item = GetLabelToIOFunctionMap().Find(label);
- FW_ASSERT(item);
-
- // Write the class label out to the archive.
- PrivOutputObject(writableStream, kMetaClassTypeConstant, item);
-
- // Write the 'object' data out to the archive.
- PrivOutputObject(writableStream, label, object);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::Initialize
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivArchiver::Initialize(FW_SPrivArchiverGlobals& globals)
- {
- globals.gNameToLabelMap =
- new FW_CPrivNameToLabelMap(FW_PrivCompareNames);
- globals.gLabelToIOFunctionMap =
- new FW_CPrivLabelToIOFunctionMap(FW_PrivCompareLabels);
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::Terminate
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivArchiver::Terminate()
- {
- FW_SPrivArchiverGlobals& globals = GetArchiverGlobals();
- delete globals.gNameToLabelMap;
- delete globals.gLabelToIOFunctionMap;
- }
-
- //========================================================================================
- // Struct FW_SPrivArcStr
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_SPrivArcStr::FW_SPrivArcStr
- //----------------------------------------------------------------------------------------
-
- FW_SPrivArcStr::FW_SPrivArcStr(const char* string) :
- fString(string)
- {
- FW_ASSERT(this->fString != NULL);
- }
-
- //========================================================================================
- // Struct FW_SPrivArcFun
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_SPrivArcFun::FW_SPrivArcFun
- //----------------------------------------------------------------------------------------
-
- FW_SPrivArcFun::FW_SPrivArcFun(Create create,
- Initialize initialize,
- Destroy destroy,
- Output output) :
- fCreateFunction(create),
- fInitializeFunction(initialize),
- fDestroyFunction(destroy),
- fOutputFunction(output)
- {
- #ifdef FW_DEBUG
- if (fInitializeFunction != NULL)
- FW_ASSERT(("If an initialize function is registered, a destroy function must be too", fDestroyFunction != NULL));
- #endif
- }
-
- //========================================================================================
- // Keys Matching Function
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // FW_PrivKeysMatchProc
- //----------------------------------------------------------------------------------------
-
- int FW_PrivCompareNames(void* k1, void* k2)
- {
- FW_CPrivNameToLabelPair* key1 = (FW_CPrivNameToLabelPair*) k1;
- FW_CPrivNameToLabelPair* key2 = (FW_CPrivNameToLabelPair*) k2;
- return FW_PrimitiveStringCompare(key1->fKey.fString, key2->fKey.fString);
- }
-
- int FW_PrivCompareLabels(void* k1, void* k2)
- {
- FW_CPrivLabelToIOFunctionPair* key1 = (FW_CPrivLabelToIOFunctionPair*) k1;
- FW_CPrivLabelToIOFunctionPair* key2 = (FW_CPrivLabelToIOFunctionPair*) k2;
- if (key1->fKey < key2->fKey)
- return -1;
- else if (key1->fKey == key2->fKey)
- return 0;
- else
- return 1;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::PrivCreateObject
- //----------------------------------------------------------------------------------------
-
- void* FW_CPrivArchiver::PrivCreateObject(FW_CReadableStream& readableStream,
- FW_ClassTypeConstant classLabel)
- {
- FW_SOMEnvironment ev;
- void* objectPtr = NULL;
- FW_OObjectRegistry* registry = readableStream.GetRegistry();
-
- short byValue;
- FW_ObjectRegistry_ID id;
-
- readableStream >> byValue >> id;
-
- switch (byValue)
- {
- case kIDOnly:
- {
- if (id == FW_kPrivNULLObjectID)
- objectPtr = NULL;
- else
- {
- objectPtr = registry->LookupByID(ev, id);
- FW_ASSERT(("Object registry ID was not found in registry", objectPtr != NULL));
- // If the above assertion fails, the stream is probably corrupt.
- // However, one should check to see (using a debugger) if the id is a negative
- // value. If so, then the stream may have a reference to a preregistered object,
- // but for some reason the object wasn't preregistered at runtime.
- if (objectPtr == NULL)
- FW_Failure(FW_xCorruptArchiveStream);
- }
- break;
- }
- case kIDAndValue:
- {
- // We allow for two-step construction here.
- // 1) Allocate raw memory and possibly do minimal initialization
- // 2) Finish full initialization
- // Object is registered between steps 1 and 2. Object objects
- // created during step 2 can have references back to this object.
- FW_CPrivLabelToIOFunctionPair* pair = LookupArchivingFunctions(classLabel);
- if (pair == NULL)
- pair = LookupArchivingFunctions(FW_kWildCardLabel);
- FW_ASSERT(("No registered archiving functions for class label", pair != NULL));
- if (pair == NULL)
- FW_Failure(FW_xCorruptArchiveStream);
-
- FW_SPrivArcFun* archivingFunctions = &pair->fValue;
- FW_SPrivArcFun::Create create = archivingFunctions->fCreateFunction;
- FW_ASSERT(("Attempt to create object from stream with NULL create function", create != NULL));
- if (create == NULL)
- FW_Failure(FW_xCorruptArchiveStream);
-
- objectPtr = create(readableStream, classLabel);
- FW_ASSERT(objectPtr != NULL);
- if (objectPtr == NULL)
- FW_Failure(FW_xCorruptArchiveStream);
-
- if (id != kNotInRegistry)
- registry->RegisterObjectAndID(ev, objectPtr, id);
-
- FW_SPrivArcFun::Initialize initialize = archivingFunctions->fInitializeFunction;
- if (initialize != 0)
- {
- FW_SPrivArcFun::Destroy destroy = archivingFunctions->fDestroyFunction;
- FW_ASSERT(destroy != NULL);
- if (destroy == NULL)
- FW_Failure(FW_xCorruptArchiveStream);
- FW_TRY
- {
- initialize(readableStream, classLabel, objectPtr);
- }
- FW_CATCH_BEGIN
- FW_CATCH_EVERYTHING()
- {
- destroy(objectPtr, classLabel);
- FW_THROW_SAME();
- }
- FW_CATCH_END
- }
- break;
- }
- default:
- {
- FW_ASSERT(false);
- FW_Failure(FW_xCorruptArchiveStream);
- break;
- }
- }
-
- return objectPtr;
- }
-
- //----------------------------------------------------------------------------------------
- // FW_CPrivArchiver::PrivOutputObject
- //----------------------------------------------------------------------------------------
-
- void FW_CPrivArchiver::PrivOutputObject(FW_CWritableStream& writableStream,
- FW_ClassTypeConstant classLabel,
- const void* object)
- {
- FW_SOMEnvironment ev;
-
- FW_OObjectRegistry* registry = writableStream.GetRegistry();
- FW_ObjectRegistry_ID id = registry->LookupByObject(ev, (void*) object);
-
- if (id == kNotInRegistry)
- {
- FW_CPrivLabelToIOFunctionPair* pair = LookupArchivingFunctions(classLabel);
- if (pair == NULL)
- pair = LookupArchivingFunctions(FW_kWildCardLabel);
- FW_ASSERT(("No registered archiving functions for class label", pair != NULL));
- if (pair == NULL)
- FW_Failure(FW_xCorruptArchiveStream);
-
- FW_SPrivArcFun* archivingFunctions = &pair->fValue;
- FW_SPrivArcFun::Output output = archivingFunctions->fOutputFunction;
- FW_ASSERT(output != NULL);
- if (output == NULL)
- FW_Failure(FW_xCorruptArchiveStream);
-
- id = registry->RegisterObject(ev, (void*) object);
- writableStream << kIDAndValue << id;
- output(writableStream, classLabel, object);
- }
- else
- {
- writableStream << kIDOnly << id;
- }
- }
-